﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using Coronox.SkyShell.Ntfs;
using System.Reflection;

namespace Coronox.SkyShell
{
    internal static class FolderOperator
    {
        private const int ERROR_NOT_A_REPARSE_POINT = 4390;
        private const uint IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003;
        private const int FSCTL_GET_REPARSE_POINT = 0x000900A8;
        private const int FSCTL_SET_REPARSE_POINT = 0x000900A4;
        private const int FSCTL_DELETE_REPARSE_POINT = 0x000900AC;

        private const string NonInterpretedPathPrefix = @"\??\";

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
            IntPtr InBuffer, int nInBufferSize,
            IntPtr OutBuffer, int nOutBufferSize,
            out int pBytesReturned, IntPtr lpOverlapped);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr CreateFile(
            string lpFileName,
            SsxFileAccess dwDesiredAccess,
            SsxFileShare dwShareMode,
            IntPtr lpSecurityAttributes,
            SsxFileMode dwCreationDisposition,
            SsxFileAttributes dwFlagsAndAttributes,
            IntPtr hTemplateFile);



        internal static bool Move(string source, string target, bool showUI)
        {
            //test something here
            showUI = true;

            DirectoryInfo sourceDi = new DirectoryInfo(source);
            if (sourceDi.Exists)
            {
                DirectoryInfo targetDi = new DirectoryInfo(target);
                File.SetAttributes(source, FileAttributes.Normal);
                try
                {
                    if (showUI)
                    {
                        Microsoft.VisualBasic.FileIO.FileSystem.MoveDirectory(source, target, Microsoft.VisualBasic.FileIO.UIOption.AllDialogs, Microsoft.VisualBasic.FileIO.UICancelOption.ThrowException);
                        //      Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(
                    }
                    else
                    {
                        //no UI
                        if (!targetDi.Exists)
                        {
                            sourceDi.MoveTo(targetDi.FullName);
                        }
                        else
                            return false;
                    }
                    return true;
                }
                catch (OperationCanceledException)
                {
                    //OK this happens in two situations
                    //1. User did cancel
                    //2. Move was completed but a Window or file was open somwhere in the folder
                }
                if (Directory.Exists(source))
                {
                    //directory is still here, lets see whether it's empty
                    var files = Directory.EnumerateFiles(source);
                    var dirs = Directory.EnumerateDirectories(source);
                    if (files.Count() == 0 && dirs.Count() == 0)
                    {
                        //it's empty. lets try to delete
                        Directory.Delete(source);
                        return true;
                    }
                    else
                    {
                        //ok the move failed
                        return false;
                    }
                }
                else
                {
                    //ok directory is gone and we good to go
                    return true;
                }
            }
            else
                return false;

        }

        internal static bool Copy(string source, string target)
        {
            DirectoryInfo sourceDi = new DirectoryInfo(source);
            if (sourceDi.Exists)
            {
                DirectoryInfo targetDi = new DirectoryInfo(target);
                File.SetAttributes(source, FileAttributes.Normal);
                try
                {
                    Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(source, target, Microsoft.VisualBasic.FileIO.UIOption.AllDialogs, Microsoft.VisualBasic.FileIO.UICancelOption.ThrowException);
                    return true;
                }
                catch (OperationCanceledException)
                {
                    return false;
                }
            }
            else
                return false;

        }


        //internal static bool CreateSurrogate(string source, string target)
        //{
        //    DirectoryInfo targetDi = new DirectoryInfo(target);
        //    if (targetDi.Exists)
        //    {
        //        DirectoryInfo sourceDi = new DirectoryInfo(source);
        //        if (!sourceDi.Exists)
        //        {
        //            Process p = new Process();
        //            ProcessStartInfo psi = new ProcessStartInfo();
        //            psi.FileName = "cmd.exe";
        //            psi.UseShellExecute = false;
        //            psi.CreateNoWindow = true;
        //            psi.WindowStyle = ProcessWindowStyle.Hidden;
        //            psi.Arguments = " /C mklink /J \"" + source + "\" \"" + target + "\"";
        //            // psi.RedirectStandardOutput = true;
        //            //  psi.RedirectStandardError = true;
        //            p.StartInfo = psi;

        //            //Console.WriteLine("{0} {1}", psi.FileName, psi.Arguments);

        //            p.Start();

        //            p.WaitForExit();

        //            return p.ExitCode == 0;
        //        }
        //        else
        //            return false;
        //    }
        //    else
        //        return false;

        //}

        internal static bool CreateFolderIcon(string target)
        {
            IniFile newDesktopini = new IniFile(new DirectoryInfo(target).FullName + @"\Desktop.ini");

            var loc = System.Reflection.Assembly.GetExecutingAssembly().Location;
            FileInfo fi = new FileInfo(loc);
            loc = fi.DirectoryName;
            var iconpath = Path.Combine(loc, "SsxFolderIconLight.ico");
            string recentIniPath = string.Empty;
            bool iniResult = false;

            recentIniPath = newDesktopini.IniReadValue(".ShellClassInfo", "IconResource");

            if (!string.IsNullOrEmpty(recentIniPath) && iconpath != recentIniPath)
            {
                iniResult = newDesktopini.IniWriteValue(".ShellClassInfo", "IconResourceSkyShellExBackup", recentIniPath);
            }
            iniResult = newDesktopini.IniWriteValue(".ShellClassInfo", "IconResource", string.Format("{0}", iconpath, 1));

            if (iniResult)
            {
                File.SetAttributes(newDesktopini.Path, FileAttributes.System | FileAttributes.Hidden);
                File.SetAttributes(target, FileAttributes.ReadOnly);
            }

            return iniResult;
        }




        internal static bool RemoveFolderIcon(string target)
        {
            IniFile newDesktopini = new IniFile(new DirectoryInfo(target).FullName + @"\Desktop.ini");
            bool iniResult = newDesktopini.IniDeleteValue(".ShellClassInfo", "IconResource");
            string recentIniPath = string.Empty;


            if (iniResult)
            {
                recentIniPath = newDesktopini.IniReadValue(".ShellClassInfo", "IconResourceSkyShellExBackup");
                if (!string.IsNullOrEmpty(recentIniPath))
                {
                    iniResult = newDesktopini.IniWriteValue(".ShellClassInfo", "IconResource", recentIniPath);
                    if (iniResult)
                        iniResult = newDesktopini.IniDeleteValue(".ShellClassInfo", "IconResourceSkyShellExBackup");
                }
                else
                {
                    File.SetAttributes(target, FileAttributes.Normal);
                }


            }
            return iniResult;
        }

        //internal static bool DeleteSurrogate(string target)
        //{
        //    DirectoryInfo targetDi = new DirectoryInfo(target);
        //    if (targetDi.Exists)
        //    {
        //        if (IsJunction(target))
        //        {
        //            Directory.Delete(target);
        //            return true;
        //        }
        //        else
        //            return false;
        //    }
        //    else
        //        return false;
        //}


        internal static bool IsJunction(string path)
        {
            DirectoryInfo di = new DirectoryInfo(path);
            bool ret = (di.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint;
            return ret;
        }


        internal static bool IsJunctionToSkyDrive(string path)
        {
            if (!IsJunction(path))
                return false;

            return GetReparsePoint(path).Contains(SkyDrive.GetSkyDriveUserFolder());
        }


        internal static bool IsMemberOrContainsJunctionSkyDrive(string strPath)
        {
            if (IsJunctionToSkyDrive(strPath))
                return true;

            if (traverseParentDirectories(strPath).Any(f => IsJunctionToSkyDrive(f)))
                return true;

            if (traverseSubDirectories(strPath).Any(f => IsJunctionToSkyDrive(f)))
                return true;

            return false;
        }


        internal static DriveInfo GetFolderDriveInfo(string path)
        {
            var drives = DriveInfo.GetDrives();
            return drives.SingleOrDefault(x => path.ToLower().StartsWith(x.RootDirectory.FullName.ToLower()));
        }

        internal static void CreateJunction(string junctionPoint, string targetDir, bool overwrite)
        {
            targetDir = Path.GetFullPath(targetDir);

            if (!Directory.Exists(targetDir))
                throw new IOException("Target path does not exist or is not a directory.");

            if (Directory.Exists(junctionPoint))
            {
                if (!overwrite)
                    throw new IOException("Directory already exists and overwrite parameter is false.");
            }
            else
            {
                Directory.CreateDirectory(junctionPoint);
            }

            using (SafeFileHandle handle = OpenReparsePoint(junctionPoint, SsxFileAccess.GenericWrite))
            {
                byte[] targetDirBytes = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + Path.GetFullPath(targetDir));

                ReparseDataBuffer reparseDataBuffer = new ReparseDataBuffer();

                reparseDataBuffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
                reparseDataBuffer.ReparseDataLength = (ushort)(targetDirBytes.Length + 12);
                reparseDataBuffer.SubstituteNameOffset = 0;
                reparseDataBuffer.SubstituteNameLength = (ushort)targetDirBytes.Length;
                reparseDataBuffer.PrintNameOffset = (ushort)(targetDirBytes.Length + 2);
                reparseDataBuffer.PrintNameLength = 0;
                reparseDataBuffer.PathBuffer = new byte[0x3ff0];
                Array.Copy(targetDirBytes, reparseDataBuffer.PathBuffer, targetDirBytes.Length);

                int inBufferSize = Marshal.SizeOf(reparseDataBuffer);
                IntPtr inBuffer = Marshal.AllocHGlobal(inBufferSize);

                try
                {
                    Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false);

                    int bytesReturned;
                    bool result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_SET_REPARSE_POINT,
                        inBuffer, targetDirBytes.Length + 20, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);

                    if (!result)
                        ThrowLastWin32Error("Unable to create junction point.");
                }
                finally
                {
                    Marshal.FreeHGlobal(inBuffer);
                }
            }
        }

        internal static bool DeleteJunction(string junctionPoint)
        {
            if (!Directory.Exists(junctionPoint))
            {
                return false;
            }

            using (SafeFileHandle handle = OpenReparsePoint(junctionPoint, SsxFileAccess.GenericWrite))
            {
                ReparseDataBuffer reparseDataBuffer = new ReparseDataBuffer();

                reparseDataBuffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
                reparseDataBuffer.ReparseDataLength = 0;
                reparseDataBuffer.PathBuffer = new byte[0x3ff0];

                int inBufferSize = Marshal.SizeOf(reparseDataBuffer);
                IntPtr inBuffer = Marshal.AllocHGlobal(inBufferSize);
                try
                {
                    Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false);

                    int bytesReturned;
                    bool result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_DELETE_REPARSE_POINT,
                        inBuffer, 8, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);

                    if (!result)
                        ThrowLastWin32Error("Unable to delete junction point.");
                }
                finally
                {
                    Marshal.FreeHGlobal(inBuffer);
                }

                try
                {
                    //Directory.Delete(junctionPoint);
                }
                catch (IOException ex)
                {
                    throw new IOException("Unable to delete junction point.", ex);
                }
                return true;
            }
        }

        internal static string GetReparsePoint(string folderPath)
        {
            using (SafeFileHandle handle = OpenReparsePoint(folderPath, SsxFileAccess.GenericRead))
            {
                string target = InternalGetTarget(handle);
                if (target == null)
                    throw new IOException("Path is not a junction point.");

                return target;
            }
        }

        private static string InternalGetTarget(SafeFileHandle handle)
        {
            int outBufferSize = Marshal.SizeOf(typeof(ReparseDataBuffer));
            IntPtr outBuffer = Marshal.AllocHGlobal(outBufferSize);

            try
            {
                int bytesReturned;
                bool result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_GET_REPARSE_POINT,
                    IntPtr.Zero, 0, outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero);

                if (!result)
                {
                    int error = Marshal.GetLastWin32Error();
                    if (error == ERROR_NOT_A_REPARSE_POINT)
                        return null;

                    ThrowLastWin32Error("Unable to get information about junction point.");
                }

                ReparseDataBuffer reparseDataBuffer = (ReparseDataBuffer)
                    Marshal.PtrToStructure(outBuffer, typeof(ReparseDataBuffer));

                if (reparseDataBuffer.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
                    return null;

                string targetDir = Encoding.Unicode.GetString(reparseDataBuffer.PathBuffer,
                    reparseDataBuffer.SubstituteNameOffset, reparseDataBuffer.SubstituteNameLength);

                if (targetDir.StartsWith(NonInterpretedPathPrefix))
                    targetDir = targetDir.Substring(NonInterpretedPathPrefix.Length);

                return targetDir;
            }
            finally
            {
                Marshal.FreeHGlobal(outBuffer);
            }
        }

        private static SafeFileHandle OpenReparsePoint(string reparsePoint, SsxFileAccess accessMode)
        {
            SafeFileHandle reparsePointHandle = new SafeFileHandle(CreateFile(reparsePoint, accessMode,
                SsxFileShare.Read | SsxFileShare.Write | SsxFileShare.Delete,
                IntPtr.Zero, SsxFileMode.OpenExisting,
                SsxFileAttributes.BackupSemantics | SsxFileAttributes.OpenReparsePoint, IntPtr.Zero), true);

            if (Marshal.GetLastWin32Error() != 0)
                ThrowLastWin32Error("Unable to open reparse point.");

            return reparsePointHandle;
        }

        private static void ThrowLastWin32Error(string message)
        {
            throw new IOException(message, Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));
        }

        // traverse sub directories
        public static IEnumerable<string> traverseSubDirectories(string strPath)
        {
            foreach (string d in Directory.GetDirectories(strPath))
            {
                yield return d;

                foreach (string s in traverseSubDirectories(d))
                {
                    yield return s;
                }
            }
        }

        // traverse parent directories
        public static IEnumerable<string> traverseParentDirectories(string strPath)
        {
            System.IO.DirectoryInfo directoryInfo =
                        System.IO.Directory.GetParent(strPath);

            if (directoryInfo != null)
            {
                yield return directoryInfo.FullName;
                foreach (string p in traverseParentDirectories(directoryInfo.FullName))
                {
                    yield return p;
                }
            }
        }

        public static bool IsPartOfSystemFolder(string path)
        {
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.Windows)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.System)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.Programs)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.AdminTools)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.CommonAdminTools)))
            //    return true;
            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)))
            //    return true;

            //if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)))
            //    return true;

            if (IsSpecialFolder(path))
                return true;

            return false;
        }


        [DllImport("shell32.dll")]
        static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath);

        public static bool IsSpecialFolder(string folderPath)
        {
            foreach (var specialFolder in KnownFolder.getFolders())
            {

                IntPtr pPath;
                if (SHGetKnownFolderPath(specialFolder.Value, 0, IntPtr.Zero, out pPath) == 0)
                {
                    string s = System.Runtime.InteropServices.Marshal.PtrToStringUni(pPath);
                    System.Runtime.InteropServices.Marshal.FreeCoTaskMem(pPath);
                    // s now contains the path
                    if (s.Equals(folderPath, StringComparison.InvariantCultureIgnoreCase))
                        return true;
                }
            }
            return false;
        }


    }

    public static class KnownFolder
    {
        public static Dictionary<string, Guid> getFolders()
        {
            Dictionary<string, Guid> hashtable = new Dictionary<string, Guid>();

            hashtable.Add("AddNewPrograms", new Guid("de61d971-5ebc-4f02-a3a9-6c82895e5c04"));
            hashtable.Add("AdminTools", new Guid("724EF170-A42D-4FEF-9F26-B60E846FBA4F"));
            hashtable.Add("AppUpdates", new Guid("a305ce99-f527-492b-8b1a-7e76fa98d6e4"));
            hashtable.Add("CDBurning", new Guid("9E52AB10-F80D-49DF-ACB8-4330F5687855"));
            hashtable.Add("ChangeRemovePrograms", new Guid("df7266ac-9274-4867-8d55-3bd661de872d"));
            hashtable.Add("CommonAdminTools", new Guid("D0384E7D-BAC3-4797-8F14-CBA229B392B5"));
            hashtable.Add("CommonOEMLinks", new Guid("C1BAE2D0-10DF-4334-BEDD-7AA20B227A9D"));
            hashtable.Add("CommonPrograms", new Guid("0139D44E-6AFE-49F2-8690-3DAFCAE6FFB8"));
            hashtable.Add("CommonStartMenu", new Guid("A4115719-D62E-491D-AA7C-E74B8BE3B067"));
            hashtable.Add("CommonStartup", new Guid("82A5EA35-D9CD-47C5-9629-E15D2F714E6E"));
            hashtable.Add("CommonTemplates", new Guid("B94237E7-57AC-4347-9151-B08C6C32D1F7"));
            hashtable.Add("ComputerFolder", new Guid("0AC0837C-BBF8-452A-850D-79D08E667CA7"));
            hashtable.Add("ConflictFolder", new Guid("4bfefb45-347d-4006-a5be-ac0cb0567192"));
            hashtable.Add("ConnectionsFolder", new Guid("6F0CD92B-2E97-45D1-88FF-B0D186B8DEDD"));
            hashtable.Add("Contacts", new Guid("56784854-C6CB-462b-8169-88E350ACB882"));
            hashtable.Add("ControlPanelFolder", new Guid("82A74AEB-AEB4-465C-A014-D097EE346D63"));
            hashtable.Add("Cookies", new Guid("2B0F765D-C0E9-4171-908E-08A611B84FF6"));
            hashtable.Add("Desktop", new Guid("B4BFCC3A-DB2C-424C-B029-7FE99A87C641"));
            hashtable.Add("Documents", new Guid("FDD39AD0-238F-46AF-ADB4-6C85480369C7"));
            hashtable.Add("Downloads", new Guid("374DE290-123F-4565-9164-39C4925E467B"));
            hashtable.Add("Favorites", new Guid("1777F761-68AD-4D8A-87BD-30B759FA33DD"));
            hashtable.Add("Fonts", new Guid("FD228CB7-AE11-4AE3-864C-16F3910AB8FE"));
            hashtable.Add("Games", new Guid("CAC52C1A-B53D-4edc-92D7-6B2E8AC19434"));
            hashtable.Add("GameTasks", new Guid("054FAE61-4DD8-4787-80B6-090220C4B700"));
            hashtable.Add("History", new Guid("D9DC8A3B-B784-432E-A781-5A1130A75963"));
            hashtable.Add("InternetCache", new Guid("352481E8-33BE-4251-BA85-6007CAEDCF9D"));
            hashtable.Add("InternetFolder", new Guid("4D9F7874-4E0C-4904-967B-40B0D20C3E4B"));
            hashtable.Add("Links", new Guid("bfb9d5e0-c6a9-404c-b2b2-ae6db6af4968"));
            hashtable.Add("LocalAppData", new Guid("F1B32785-6FBA-4FCF-9D55-7B8E7F157091"));
            hashtable.Add("LocalAppDataLow", new Guid("A520A1A4-1780-4FF6-BD18-167343C5AF16"));
            hashtable.Add("LocalizedResourcesDir", new Guid("2A00375E-224C-49DE-B8D1-440DF7EF3DDC"));
            hashtable.Add("Music", new Guid("4BD8D571-6D19-48D3-BE97-422220080E43"));
            hashtable.Add("NetHood", new Guid("C5ABBF53-E17F-4121-8900-86626FC2C973"));
            hashtable.Add("NetworkFolder", new Guid("D20BEEC4-5CA8-4905-AE3B-BF251EA09B53"));
            hashtable.Add("OriginalImages", new Guid("2C36C0AA-5812-4b87-BFD0-4CD0DFB19B39"));
            hashtable.Add("PhotoAlbums", new Guid("69D2CF90-FC33-4FB7-9A0C-EBB0F0FCB43C"));
            hashtable.Add("Pictures", new Guid("33E28130-4E1E-4676-835A-98395C3BC3BB"));
            hashtable.Add("Playlists", new Guid("DE92C1C7-837F-4F69-A3BB-86E631204A23"));
            hashtable.Add("PrintersFolder", new Guid("76FC4E2D-D6AD-4519-A663-37BD56068185"));
            hashtable.Add("PrintHood", new Guid("9274BD8D-CFD1-41C3-B35E-B13F55A758F4"));
            hashtable.Add("Profile", new Guid("5E6C858F-0E22-4760-9AFE-EA3317B67173"));
            hashtable.Add("ProgramData", new Guid("62AB5D82-FDC1-4DC3-A9DD-070D1D495D97"));
            hashtable.Add("ProgramFiles", new Guid("905e63b6-c1bf-494e-b29c-65b732d3d21a"));
            hashtable.Add("ProgramFilesX64", new Guid("6D809377-6AF0-444b-8957-A3773F02200E"));
            hashtable.Add("ProgramFilesX86", new Guid("7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E"));
            hashtable.Add("ProgramFilesCommon", new Guid("F7F1ED05-9F6D-47A2-AAAE-29D317C6F066"));
            hashtable.Add("ProgramFilesCommonX64", new Guid("6365D5A7-0F0D-45E5-87F6-0DA56B6A4F7D"));
            hashtable.Add("ProgramFilesCommonX86", new Guid("DE974D24-D9C6-4D3E-BF91-F4455120B917"));
            hashtable.Add("Programs", new Guid("A77F5D77-2E2B-44C3-A6A2-ABA601054A51"));
            hashtable.Add("Public", new Guid("DFDF76A2-C82A-4D63-906A-5644AC457385"));
            hashtable.Add("PublicDesktop", new Guid("C4AA340D-F20F-4863-AFEF-F87EF2E6BA25"));
            hashtable.Add("PublicDocuments", new Guid("ED4824AF-DCE4-45A8-81E2-FC7965083634"));
            hashtable.Add("PublicDownloads", new Guid("3D644C9B-1FB8-4f30-9B45-F670235F79C0"));
            hashtable.Add("PublicGameTasks", new Guid("DEBF2536-E1A8-4c59-B6A2-414586476AEA"));
            hashtable.Add("PublicMusic", new Guid("3214FAB5-9757-4298-BB61-92A9DEAA44FF"));
            hashtable.Add("PublicPictures", new Guid("B6EBFB86-6907-413C-9AF7-4FC2ABF07CC5"));
            hashtable.Add("PublicVideos", new Guid("2400183A-6185-49FB-A2D8-4A392A602BA3"));
            hashtable.Add("QuickLaunch", new Guid("52a4f021-7b75-48a9-9f6b-4b87a210bc8f"));
            hashtable.Add("Recent", new Guid("AE50C081-EBD2-438A-8655-8A092E34987A"));
            hashtable.Add("RecycleBinFolder", new Guid("B7534046-3ECB-4C18-BE4E-64CD4CB7D6AC"));
            hashtable.Add("ResourceDir", new Guid("8AD10C31-2ADB-4296-A8F7-E4701232C972"));
            hashtable.Add("RoamingAppData", new Guid("3EB685DB-65F9-4CF6-A03A-E3EF65729F3D"));
            hashtable.Add("SampleMusic", new Guid("B250C668-F57D-4EE1-A63C-290EE7D1AA1F"));
            hashtable.Add("SamplePictures", new Guid("C4900540-2379-4C75-844B-64E6FAF8716B"));
            hashtable.Add("SamplePlaylists", new Guid("15CA69B3-30EE-49C1-ACE1-6B5EC372AFB5"));
            hashtable.Add("SampleVideos", new Guid("859EAD94-2E85-48AD-A71A-0969CB56A6CD"));
            hashtable.Add("SavedGames", new Guid("4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4"));
            hashtable.Add("SavedSearches", new Guid("7d1d3a04-debb-4115-95cf-2f29da2920da"));
            hashtable.Add("SEARCH_CSC", new Guid("ee32e446-31ca-4aba-814f-a5ebd2fd6d5e"));
            hashtable.Add("SEARCH_MAPI", new Guid("98ec0e18-2098-4d44-8644-66979315a281"));
            hashtable.Add("SearchHome", new Guid("190337d1-b8ca-4121-a639-6d472d16972a"));
            hashtable.Add("SendTo", new Guid("8983036C-27C0-404B-8F08-102D10DCFD74"));
            hashtable.Add("SidebarDefaultParts", new Guid("7B396E54-9EC5-4300-BE0A-2482EBAE1A26"));
            hashtable.Add("SidebarParts", new Guid("A75D362E-50FC-4fb7-AC2C-A8BEAA314493"));
            hashtable.Add("StartMenu", new Guid("625B53C3-AB48-4EC1-BA1F-A1EF4146FC19"));
            hashtable.Add("Startup", new Guid("B97D20BB-F46A-4C97-BA10-5E3608430854"));
            hashtable.Add("SyncManagerFolder", new Guid("43668BF8-C14E-49B2-97C9-747784D784B7"));
            hashtable.Add("SyncResultsFolder", new Guid("289a9a43-be44-4057-a41b-587a76d7e7f9"));
            hashtable.Add("SyncSetupFolder", new Guid("0F214138-B1D3-4a90-BBA9-27CBC0C5389A"));
            hashtable.Add("System", new Guid("1AC14E77-02E7-4E5D-B744-2EB1AE5198B7"));
            hashtable.Add("SystemX86", new Guid("D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27"));
            hashtable.Add("Templates", new Guid("A63293E8-664E-48DB-A079-DF759E0509F7"));
            hashtable.Add("TreeProperties", new Guid("5b3749ad-b49f-49c1-83eb-15370fbd4882"));
            hashtable.Add("UserProfiles", new Guid("0762D272-C50A-4BB0-A382-697DCD729B80"));
            hashtable.Add("UsersFiles", new Guid("f3ce0f7c-4901-4acc-8648-d5d44b04ef8f"));
            hashtable.Add("Videos", new Guid("18989B1D-99B5-455B-841C-AB7C74E4DDFC"));
            hashtable.Add("Windows", new Guid("F38BF404-1D43-42F2-9305-67DE0B28FC23"));

            return hashtable;
        }
    }

}
